/*
 * @Author: song
 * @Description:摄像机面板
 * @Date: 2024年05月03日 星期五 22:05:43
 * @Modify:
 */

using Function.SkillEditor.Runtime;
using SCore.Editor.WindowDraw;
using UnityEditor;
using UnityEngine;

namespace Function.SkillEditor.Editor
{
    public class SkillCameraSubWindow : IESubWindow
    {
        private static float PITCH_SPEED = 0.5f;
        private static float YAW_SPEED = 0.5f;
        private static float DRAG_SPEED = 0.02f;
        private static float ZOOM_SPEED = 0.5f;

        private Camera _camera;
        private RenderTexture _renderTexture;
        private Rect _viewRect = new Rect(0, 0, 0, 0);
        private Rect _lastViewRect = new Rect(0, 0, 0, 0);

        //逻辑判断
        private bool _mIsRotatingCamera = false;
        private bool _mIsDraggingCamera = false;
        private Vector2 _mLastDragMousePos = Vector2.zero;
        private bool _mIsViewRectActive = false;

        // 预览摄像机的控制
        private float mViewDistance = 15.0f;
        private float mPitchAngle = 45;
        private float mYawAngle = 0;
        private Vector3 mFocusOffset = Vector3.zero;

        public SkillCameraSubWindow(EditorWindow window) : base(window)
        {
        }

        public void SetUpCamera()
        {
            if (_camera != null)
                return;
            GameObject cameraObj = new GameObject("Editor Camera", typeof(Camera));
            _camera = cameraObj.GetComponent<Camera>();
            // 设置相机
            _camera.clearFlags = CameraClearFlags.SolidColor;
            _camera.backgroundColor = EditorDrawHelp._ivory6;
            _renderTexture = new RenderTexture(100, 100, 24, RenderTextureFormat.ARGB32);
            _renderTexture.Create();
            _camera.targetTexture = _renderTexture;

            mYawAngle = 90f;
            // 绘制网格线
            SceneGridDrawer grid = _camera.gameObject.GetOrAddComponent<SceneGridDrawer>();
            grid.mainColor = EditorDrawHelp._ivory4;
            grid.subColor = 0.5f * grid.mainColor;
            grid.subCounts = 5;
            grid.halfSize = 10;
        }

        public void DrawCamera()
        {
            if (_renderTexture == null)
                return;

            _viewRect = _rect;
            GUI.DrawTexture(new Rect(_viewRect.x - 2.5f, _viewRect.y - 3, _viewRect.width + 6, _viewRect.height + 3),
                _renderTexture);
        }

        private void OnViewRectSizeChanged()
        {
            if (_camera == null)
                return;

            int width = Mathf.Max(10, (int)_viewRect.width);
            int height = Mathf.Max(10, (int)_viewRect.height);

            _renderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
            _renderTexture.Create();
            _camera.targetTexture = _renderTexture;
        }

        private void OnViewRectLeftMouseDown()
        {
            _mIsDraggingCamera = true;
            _mLastDragMousePos = Event.current.mousePosition;
        }

        private void OnViewRectLeftMouseUp()
        {
            _mIsDraggingCamera = false;
        }

        private void OnViewRectRightMouseDown()
        {
            _mIsRotatingCamera = true;
            _mLastDragMousePos = Event.current.mousePosition;
        }

        private void OnViewRectRightMouseUp()
        {
            _mIsRotatingCamera = false;
        }

        private bool Vector4Equal(Vector4 v1, Vector4 v2, float epsilon = 0.0001f)
        {
            return (FloatEqual(v1.x, v2.x, epsilon) &&
                    FloatEqual(v1.y, v2.y, epsilon) &&
                    FloatEqual(v1.z, v2.z, epsilon) &&
                    FloatEqual(v1.w, v2.w, epsilon));
        }

        // 浮点数的比较
        public static bool FloatEqual(float val1, float val2, float epsilon = 0.0001f)
        {
            float temp = val1 - val2;
            temp = temp < 0 ? temp * -1f : temp;
            return temp < epsilon;
        }

        private void UpdateViewCamera()
        {
            // 更新摄像机位置
            if (_camera != null)
            {
                float posY = mViewDistance * Mathf.Sin(mPitchAngle * Mathf.Deg2Rad);
                float posX = mViewDistance * Mathf.Cos(mPitchAngle * Mathf.Deg2Rad) *
                             Mathf.Cos(mYawAngle * Mathf.Deg2Rad);
                float posZ = mViewDistance * Mathf.Cos(mPitchAngle * Mathf.Deg2Rad) *
                             Mathf.Sin(mYawAngle * Mathf.Deg2Rad);

                Vector3 focusPos = Vector3.zero;
                focusPos += mFocusOffset;

                _camera.transform.position = focusPos + new Vector3(posX, posY, posZ);
                _camera.transform.LookAt(focusPos);
                _camera.Render();
            }
        }

        public override void OnEnable()
        {
            SetUpCamera();
            OnViewRectSizeChanged();
            base.OnEnable();
        }

        public override void OnGUI()
        {
            DrawTitle("相机");
            DrawCamera();
        }

        public override void Update()
        {
            UpdateViewCamera();
        }

        public override void UpdateEvent(Event e)
        {
            bool mouseInViewRect = _viewRect.Contains(e.mousePosition);

            switch (Event.current.type)
            {
                case EventType.MouseDown:
                    if (Event.current.button == 0)
                    {
                        if (mouseInViewRect)
                            OnViewRectLeftMouseDown();
                    }
                    else if (Event.current.button == 1)
                    {
                        if (mouseInViewRect)
                            OnViewRectRightMouseDown();
                    }

                    break;

                case EventType.MouseUp:
                    if (Event.current.button == 0)
                    {
                        if (_mIsDraggingCamera)
                            OnViewRectLeftMouseUp();
                    }
                    else if (Event.current.button == 1)
                    {
                        if (_mIsRotatingCamera)
                            OnViewRectRightMouseUp();
                    }

                    break;
            }

            // 是否激活中央预览区的鼠标事件这里单独判断
            if (Event.current.type == EventType.MouseDown)
            {
                if (mouseInViewRect)
                    _mIsViewRectActive = true;
                else
                    _mIsViewRectActive = false;
            }

            // 调整预览摄像机
            if (_mIsRotatingCamera)
            {
                Vector2 delta = Event.current.mousePosition - _mLastDragMousePos;
                _mLastDragMousePos = Event.current.mousePosition;

                mPitchAngle += delta.y * PITCH_SPEED;
                mYawAngle -= delta.x * YAW_SPEED;

                mPitchAngle = Mathf.Clamp(mPitchAngle, -89.0f, 89.0f);
            }

            if (_mIsDraggingCamera)
            {
                Vector2 delta = Event.current.mousePosition - _mLastDragMousePos;
                _mLastDragMousePos = Event.current.mousePosition;

                Vector3 offset = new Vector3(-DRAG_SPEED * delta.x, DRAG_SPEED * delta.y, 0);
                offset = _camera.transform.TransformVector(offset);

                mFocusOffset += offset;
            }

            if (_mIsViewRectActive && Event.current.type == EventType.ScrollWheel)
            {
                mViewDistance += Event.current.delta.y * ZOOM_SPEED;
                mViewDistance = Mathf.Clamp(mViewDistance, 1.0f, 100.0f);
            }

            // 窗口大小调整后, 中央镜头区对应的RenderTexture大小要调整
            if (!Vector4Equal(new Vector4(_viewRect.xMin, _viewRect.yMin, _viewRect.width, _viewRect.height),
                    new Vector4(_lastViewRect.xMin, _lastViewRect.yMin, _lastViewRect.width, _lastViewRect.height)))
            {
                _lastViewRect = _viewRect;
                OnViewRectSizeChanged();
            }
        }
    }
}